package br.usp.ime.entities;

import java.io.Serializable;
import java.util.*;
import java.text.*;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "tasks")
public class Task implements Serializable {

	private Long id;
	private String name;
	private String description;
	private User taskOwner;
	private EvaluationForm evaluationForm;
	private Date duedate;
	private List<User> usersInCharge = null;
	private List<User> evaluatorsUsers = null;
	private List<SubmittedFile> submittedFiles = null;
	private List<Topic> topics; 
	
	private boolean topic1 = false;
	private boolean topic2 = false;
	private boolean topic3 = false;
	private boolean topic4 = false;

	public Task() {
		evaluationForm = new EvaluationForm();
		usersInCharge = new ArrayList<User>();
		evaluatorsUsers = new ArrayList<User>(); 
		submittedFiles = new ArrayList<SubmittedFile>();
		topics = new ArrayList<Topic>();
	}

	public void addSubmittedFile(SubmittedFile sf) {
		submittedFiles.add(sf);
	}
	
	public void removeSubmittedFile(SubmittedFile sf) {
		submittedFiles.remove(sf);
	}
	
	@OneToMany(mappedBy = "relatedTask", fetch=FetchType.EAGER) // Verificar se será necessário mais magia do Hibernate aqui.
	public List<SubmittedFile> getSubmittedFiles() {
		return submittedFiles;
	}

	public void setSubmittedFiles(List<SubmittedFile> submittedFiles) {
		this.submittedFiles = submittedFiles;
	}

	@Id
	@GeneratedValue
	@Column(name = "TASK_ID")
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Column(name = "TASK_NAME")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name = "TOPIC1")
	public boolean isTopic1() {
		return topic1;
	}

	public void setTopic1(boolean topic1) {
		this.topic1 = topic1;
	}

	@Column(name = "TOPIC2")
	public boolean isTopic2() {
		return topic2;
	}

	public void setTopic2(boolean topic2) {
		this.topic2 = topic2;
	}

	@Column(name = "TOPIC3")
	public boolean isTopic3() {
		return topic3;
	}

	public void setTopic3(boolean topic3) {
		this.topic3 = topic3;
	}

	@Column(name = "TOPIC4")
	public boolean isTopic4() {
		return topic4;
	}

	public void setTopic4(boolean topic4) {
		this.topic4 = topic4;
	}

	@Column(name = "DUE_DATE")
	public Date getDuedate() {
		return duedate;
	}

	public void setDuedate(String date) throws ParseException {
		SimpleDateFormat dataFormated = new SimpleDateFormat("dd/MM/yyyy");
		Date dueDate = null;
		try {
			dueDate = dataFormated.parse(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.duedate = dueDate;
	}

	@Column(name = "TASK_DESCRIPTION")
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
			CascadeType.REFRESH }, fetch=FetchType.LAZY)
	@JoinColumn(name = "TASK_OWNER_LOGIN")
	public User getTaskOwner() {
		return taskOwner;
	}

	public void setTaskOwner(User taskOwner) {
		this.taskOwner = taskOwner;
	}

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "FORM_ID")
	public EvaluationForm getEvaluationForm() {
		return evaluationForm;
	}

	public void setEvaluationForm(EvaluationForm evaluationForm) {
		this.evaluationForm = evaluationForm;
	}

	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
			CascadeType.REFRESH }, fetch = FetchType.LAZY, mappedBy = "tasksInChargeOf", targetEntity = User.class)
	@org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE })
	public List<User> getUsersInCharge() {
		return usersInCharge;
	}

	public void setUsersInCharge(List<User> usersInCharge) {
		this.usersInCharge = usersInCharge;
	}

	public void addUserInCharge(User userInCharge) {
		if (usersInCharge == null)
			usersInCharge = new ArrayList<User>();
		usersInCharge.add(userInCharge);
	}

	public boolean isUserInCharge(User user) {
		return (user != null && usersInCharge != null && usersInCharge
				.contains(user));
	}

	
  	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
			CascadeType.REFRESH }, fetch = FetchType.LAZY, mappedBy = "tasksByEvaluatorsUsers", targetEntity = User.class)
	@org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE })
	public List<User> getEvaluatorsUsers() {
		return evaluatorsUsers;
	}

	public void setEvaluatorsUsers(List<User> evaluatorsUsers) {
		this.evaluatorsUsers = evaluatorsUsers;
	}

	public void addEvaluatorUser(User evaluatorUser) {
		if (this.evaluatorsUsers == null)
			this.evaluatorsUsers = new ArrayList<User>();
		this.evaluatorsUsers.add(evaluatorUser);
	}

	public boolean isEvaluatorUser(User user) {
		return (user != null && evaluatorsUsers != null && evaluatorsUsers
				.contains(user));
	}
	
	public boolean isEvaluatorUser(String login) {
		if (login != null && evaluatorsUsers != null)
			for(Iterator<User> i = evaluatorsUsers.iterator();i.hasNext();)
				if (i.next().getLogin().equals(login))
					return true;
		return false;
	}

  	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
			CascadeType.REFRESH }, fetch = FetchType.LAZY, mappedBy = "tasks", targetEntity = Topic.class)
	@org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE })
	public List<Topic> getTopics() {
		return topics;
	}

	public void setTopics(List<Topic> topics) {
		this.topics = topics;
	}		
	
	public void addTopic(Topic topic) {
		if (this.topics == null)
			this.topics = new ArrayList<Topic>();
		this.topics.add(topic);
	}

	public boolean isTopic(Topic topic) {
		return (topic != null && topics != null && topics.contains(topic));
	}	

	public boolean isTopic(Integer id) {
		if(id != null && topics != null)
			for(Iterator<Topic> i = topics.iterator();i.hasNext();)
				if(i.next().getId() == id)
					return true;
			
		return false;
	}
	
	
	public void copyTask(Task task) {
		name = task.getName();
		description = task.getDescription();
		duedate = task.getDuedate();
		topic1 = task.isTopic1();
		topic2 = task.isTopic2();
		topic3 = task.isTopic3();
		topic4 = task.isTopic4();
	}

}
